package com.ssky.bean.validator.core;

import com.ssky.bean.validator.core.exception.VldException;
import com.ssky.bean.validator.util.ExpUtil;

/**
 * @Author: ssky
 * @Date: 2021/07/30
 * @Description:
 * “属性返回内容” 表达式
 * <li/>支持常量、取值表达式；不支持算术表达式
 * #--> 没有任何内容 null
 * c--> constant:常量
 * s--> ${$this}:当前属性自己的值
 * t--> ${$this. }:当前值的其他属性（单级）
 * l--> ${$local. }:属性所属对象的其他属性取值（单级）
 * b--> ${$bean. }:所属最外层对象的全路径属性取值（多级）
 * x--> ${$context. }:上下文中
 */
public class ValueExp {

    public static final char VExpFlag_Self = 's';
    public static final char VExpFlag_Constant = 'c';
    public static final char VExpFlag_This = 't';
    public static final char VExpFlag_Local = 'l';
    public static final char VExpFlag_Bean = 'b';
    public static final char VExpFlag_Null = '#';
    public static final char VExpFlag_Context = 'x';


    /**
     * “属性返回内容” 表达式
     * <li/>支持常量、取值表达式；不支持算术表达式
     * #--> 没有任何内容 null
     * c--> constant:常量
     * s--> ${$this}:当前属性自己的值
     * t--> ${$this. }:当前值的其他属性（单级）
     * l--> ${$local. }:属性所属对象的其他属性取值（单级）
     * b--> ${$bean. }:所属最外层对象的全路径属性取值（多级）
     * x--> ${$context. }:上下文中
     */
    public final char vExpFlag;

    /**
     * 去除表达式后的元素内容；
     * <p/>比如：${$local.abd }  --> abd
     */
    public final String vExp;

    public static final ValueExp ValueExpSelf = new ValueExp(VExpFlag_Self, "");
    public static final ValueExp ValueExpNull = new ValueExp(VExpFlag_Null, null);

    private ValueExp(char vExpFlag, String vExp) {
        this.vExpFlag = vExpFlag;
        this.vExp = vExp;
    }

    public boolean isSelf() {
        return this.vExpFlag == VExpFlag_Self;
    }

    public static ValueExp genValueExp(String valueExpStr) {
        ValueExp exp = null;
        if (valueExpStr != null) {
            if (ExpUtil.isVariable(valueExpStr)) {
                String vExp = ExpUtil.expParse(valueExpStr);
                if ("$this".equals(vExp)) {
                    exp = ValueExpSelf;
                } else if (vExp.startsWith("$this.")) {
                    exp = new ValueExp(VExpFlag_This, vExp.substring("$this.".length()));
                } else if (vExp.startsWith("$local.")) {
                    exp = new ValueExp(VExpFlag_Local, vExp.substring("$local.".length()));
                } else if (vExp.startsWith("$bean.")) {
                    exp = new ValueExp(VExpFlag_Bean, vExp.substring("$bean.".length()));
                } else if (vExp.startsWith("$context.")) {
                    exp = new ValueExp(VExpFlag_Context, vExp.substring("$context.".length()));
                } else {
                    throw new VldException(" 'valueExpStr'(" + valueExpStr + ") Content that does not meet expectations!");
                }
            } else {//常量
                exp = new ValueExp(VExpFlag_Constant, valueExpStr);
            }
        } else {//为null(与空不同)，默认
            exp = ValueExpNull;
        }
        return exp;
    }

    public boolean isConstant() {
        return this.vExpFlag == VExpFlag_Constant;
    }

    public boolean isThis() {
        return this.vExpFlag == VExpFlag_This;
    }

    public boolean isLocal() {
        return this.vExpFlag == VExpFlag_Local;
    }

    public boolean isBean() {
        return this.vExpFlag == VExpFlag_Bean;
    }

    public boolean isContext() {
        return this.vExpFlag == VExpFlag_Context;
    }

    public boolean isNull() {
        return this.vExpFlag == VExpFlag_Null;
    }
}
